//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//********************************************************* 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Microsoft.TridentWordAddIn.Common;
using Microsoft.Research.DataLayer;

namespace Microsoft.TridentWordAddIn.Server
{
    public class ParameterHelper
    {
        /// <summary>
        /// Determines whether [is complex type] [the specified type].
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>
        /// 	<c>true</c> if [is complex type] [the specified type]; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsComplexType(string type)
        {
            switch (type)
            {
                case "System.String":
                case "System.Int16":
                case "System.Int32":
                case "System.Int64":
                case "System.UInt16":
                case "System.UInt32":
                case "System.UInt64":
                case "System.Byte[]":
                case "System.Boolean":
                case "System.Decimal":
                case "System.Double":
                case "System.DateTime":
                case "System.Guid":
                case "System.Object":
                case "System.Uri":
                case "text/plain":
                case "text/html":
                case "image/gif":
                case "image/jpg":
                case "image/bmp":
                case "image/png":
                case "System.IO.FileInfo":
                case "System.IO.DirectoryInfo":
                    return false;
            }

            return true;
        }

        /// <summary>
        /// Parses the XML.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static string ParseComplexType(string value)
        {
            StringBuilder returnString = new StringBuilder();
            XmlDocument xmlDocument = new XmlDocument();
            try
            {
                xmlDocument.LoadXml(value);
                foreach (XmlNode node in xmlDocument.ChildNodes)
                {
                    if (node.NodeType == XmlNodeType.Element)
                    {
                        foreach (XmlNode childNode in node.ChildNodes)
                        {
                            returnString.Append(childNode.Name);
                            returnString.Append(":");
                            returnString.Append(childNode.InnerText);
                            returnString.Append(" ");
                        }
                    }
                }
            }
            catch (Exception)
            {
                return value;
            }

            xmlDocument = null;
            return returnString.ToString().TrimEnd();
        }

        /// <summary>
        /// Gets the value.
        /// </summary>
        /// <param name="workflowParam">The workflow param.</param>
        /// <param name="jobParam">The job param.</param>
        /// <returns></returns>
        public static string GetValue(WorkflowParameter workflowParam, JobParameter jobParam)
        {
            string value = string.Empty;
            if (workflowParam.IsComplexType)
            {
                if (jobParam != null)
                {
                    if (!jobParam.ComplexParsedValue.IsNullOrEmpty())
                    {
                        value = jobParam.ComplexParsedValue;
                    }
                    else
                    {
                        value = ParameterHelper.ParseComplexType(jobParam.Value);
                        jobParam.ComplexParsedValue = value;
                    }
                }
                else
                {
                    value = ParameterHelper.ParseComplexType(workflowParam.DisplayValue);
                    workflowParam.ComplexParsedValue = value;
                }
            }
            else
            {
                value = jobParam == null ? workflowParam.DisplayValue : jobParam.Value;
            }

            return value;
        }

        /// <summary>
        /// Converts to job parameter.
        /// </summary>
        /// <param name="param">The param.</param>
        /// <returns></returns>
        public static JobParameter ConvertToJobParameter(ActivityInstanceParameter param)
        {
            JobParameter jobParam = new JobParameter();
            jobParam.ActivityName = param.ParameterAssignment.ActivityParameter.Activity.Name;
            jobParam.Name = param.ParameterAssignment.ActivityParameter.Name;
            jobParam.Type = param.ParameterAssignment.ActivityParameter.Type;
            jobParam.Value = param.ParamValue;

            return jobParam;
        }

        /// <summary>
        /// Converts to workflow parameter.
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        /// <returns></returns>
        public static WorkflowParameter ConvertToWorkflowParameter(ParameterAssignment parameter)
        {
            WorkflowParameter param = new WorkflowParameter();
            param.Name = parameter.ActivityParameter.Name;
            param.Label = parameter.ActivityParameter.Label;
            param.IsBound = parameter.IsBound;
            param.Description = parameter.ActivityParameter.Description;
            param.IsInput = parameter.ActivityParameter.Direction == DirectionType.Input ? true : false;
            param.Type = parameter.ActivityParameter.Type;
            param.OutputType = parameter.Type;
            param.IsComplexType = IsComplexType(param.IsInput ? param.Type : param.OutputType);
            param.BelongsToActivity = parameter.ActivityParameter.Activity.Name;

            if (param.IsBound)
            {
                param.Value = parameter.BoundTo.Instance.Name + "." + parameter.BoundToPath;
            }
            else
            {
                param.Value = param.IsInput ? parameter.CurrentValue : parameter.Type;
            }
            return param;
        }
    }
}
